--[[
@classmod Map
a Map assemble layers and markers
no marker can be added without creating a map first
a map has a name, a width, and a height (in tile units)
]]

local bitser = require (LIB_PATH.."bitser")
local Marker = require ("marker")
local lume = require (LIB_PATH .. "lume")
local Layers = require "layers"

local output_list = function(list)
	return lume.reduce(lume.map(list, function (v)
		return string.format ("%s (X:%i Y:%i)", v.name, v.x, v.y)
									end),
										 function(v, w)
					return string.format("%s %s", v, w)
	end)
end

return pl.class {
	_name = "Map",
	
	_init = function (self, name, w, h)
		self.name = name or "untitledmap"
		self.w, self.h = w, h
		self.layers = Layers()
		self.markers = {}
	end,
	
	update = function (self)
		
	end,
	
	draw = function (self)
		self.layers:draw()
		lume.each(self.markers, function (m) m:draw() end)
	end,
	
	marker_add = function (self, name, x, y)
		local x = x or 0
		local y = y or 0
		if not name then return "marker need a name" end
		local m = self:marker_get(name)
		local n = self:marker_get(x, y)
		if m then 
			return string.format("a marker with name %s already exists at x: %i y: %i", m.name, m.x, m.y)
		end
		if n then 
			return string.format("a marker with position %i %i already exists with name ", n.x, n.y, n.name)
		end
		local mark = Marker(name, x, y)
		table.insert(self.markers, mark)
		Sled.current_marker = mark
		return string.format("added marker %s at x: %i y:%i", name, x, y)
	end,
	
	marker_get = function (self, v, u)
		for k, m in ipairs(self.markers) do
			if type(v) == "string" then
				if m:get_name() == v then return m end
			elseif type(v) == "number" and type(u) == "number" then
				if m.x == v and m.y == u then return m end
			end
		end
		return 
	end,
	
	marker_remove = function (self, name)
		local m = self:get_marker(name)
		if not self:get_marker(name) then
			return "no marker with name " .. name
		end
		lume.remove(self.markers, m)
	end,
	
	markers_list = function (self)
		if #self.markers == 0 then return end
		return output_list (self.markers)
	end,
	
	get_dimensions = function (self)
		return self.w, self.h
	end,
	
	make_layer = function (self, name, z)
		local l = self.layers:add(name, z, self.w, self.h)
		Sled.current_layer = l
	end,
	
	get_name = function (self)
		return string.match(self.name, "(%a+)%(*")
	end,
	
	rename = function (self, str)
		local count = lume.count(Sled.maps, function (m)
			return str == m:get_name()
		end)
		if count > 0 then
			str = str .. "("..(count+1)..")"
		end
		self.name = str
	end,
	
	export = function (self, filename)
		local to = "maps/"..filename..".map" 
		self.name = filename or self:get_name()
		local l_t = lume.map(self.layers.tbl, function (l)
			return {
				name = l.name,
				z = l.z,
				w = l.w,
				h = l.h,
				str = l:get_idata():getString()
				}
		end)
		local m_t = lume.map(self.markers, function(m)
			return { name = m.name, x = m.x, y = m.y }
		end)
		local map_exp = {
			name = self.name, 
			w = self.w, 
			h = self.h, 
			layers = l_t, 
			markers = m_t
			}
		local exp_str = pl.pretty.write(map_exp)
		_lf.write(to, exp_str)
	end,
}
